package com.rexolar.openapi.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.benmanes.caffeine.cache.Cache;
import com.rexolar.openapi.bean.*;
import com.rexolar.openapi.bean.request.AlarmsPageRequest;
import com.rexolar.openapi.config.CustomConfig;
import com.rexolar.openapi.constants.ApiConstant;
import com.rexolar.openapi.db.mapper.GatewayCredentialsMapper;
import com.rexolar.openapi.db.mapper.SaasUserInfoMapper;
import com.rexolar.openapi.enums.DeviceTypeEnum;
import com.rexolar.openapi.enums.ErrorCodeEnum;
import com.rexolar.openapi.exception.BaseException;
import com.rexolar.openapi.exception.TokenException;
import com.rexolar.openapi.utlis.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName RexolarApiClient
 * @Description:
 * @Author: zhusiyu
 * @CreateDate: 2024/12/11 19:41	//创建时间
 */
@Slf4j
@Service
public class RexolarApiClient {
    private static final long ONLINE_MILLISECOND = 10 * 60 * 1000;

    private static Map<String, String> modelMap = new HashMap<>();
    private static Map<String, Integer> modelOnlineMap = new HashMap<>();
    static {
        modelMap.put("QYL008", "人体存在");
        modelMap.put("LF0053", "嵌入式16A插座（10A）");
        modelMap.put("TS011F", "计量空开 （速通）");
        modelMap.put("RG5310", "吸顶网关");
        modelMap.put("RT0103", "三键单火开关");
        modelMap.put("QYL001", "门磁");
        modelMap.put("QYL002", "水浸");
        modelMap.put("QYL003", "紧急按钮");
        modelMap.put("QYL004", "温湿度计");
        modelMap.put("QYL005", "烟感");
        modelMap.put("QYL007", "PIR");
        modelMap.put("HomY001", "空调网关 （M08）");
        modelMap.put("RT0101", "一键单火开关");
        modelMap.put("LF0049", "空调面板");
        modelMap.put("WR0023", "红外转发");
        modelMap.put("RH0070", "64路空调网关");
        modelMap.put("UNDEFINED", "未定义");

        modelOnlineMap.put("QYL001", 60 * 60 * 1000);
        modelOnlineMap.put("QYL002", 60 * 60 * 1000);
        modelOnlineMap.put("QYL003", 60 * 60 * 1000);
        modelOnlineMap.put("QYL007", 60 * 60 * 1000);
        modelOnlineMap.put("QYL004", 120 * 60 * 1000);
        modelOnlineMap.put("QYL005", 60 * 60 * 1000);

    }
    private static final String GW = "gw";

    @Autowired
    private RestTemplate restTemplate;

    @Resource
    SaasUserInfoMapper saasUserInfoMapper;

    @Resource
    GatewayCredentialsMapper gatewayCredentialsMapper;

    @Autowired
    private CustomConfig customConfig;

    @Autowired
    private Cache<String, String> userTokenCache;

    private Map<String, Object> getMethod(String url, String token){
        HttpHeaders headers = new HttpHeaders();
        Map<String, Object> responseBody = new HashMap<>();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);
        HttpEntity<String> entity = new HttpEntity<>(null, headers);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );
            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getMethod 执行结束： url:{},  statusCode={}, 结果={}", url, statusCode, responseEntity);
                responseBody.put("result", false);
                return responseBody;
            }
            responseBody = responseEntity.getBody();
            responseBody.put("result", true);
            return responseBody;
        } catch (HttpClientErrorException e) {
            log.error("getMethod HttpClientErrorException failed. url:{}", url, e);
            throw e;
        }
    }

    public Map<String, Object> getAuthUser(String token) {
        String url = customConfig.getHttpApi() + ApiConstant.AUTH_USER;
        return getMethod(url, token);
    }

    /**
     * 获取Token
     * fixedRate: 单位ms
     */
    public Map authLogin(String username, String password) {
        log.info("##  获取 JWT Token");

        HttpHeaders headers = new HttpHeaders();
        // 构建请求体的 JSON 字符串
        HashMap<String, String> requestBodyMap = new HashMap<>();
        requestBodyMap.put("username", username);
        requestBodyMap.put("password", password);
        String requestBody = JSON.toJSONString(requestBodyMap);

        HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);

        String url = customConfig.getHttpApi() + ApiConstant.AUTH_LOGIN;
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## authLogin 执行结束： url:{},requestBodyMap：{},  statusCode={}, 结果={}", url, requestBodyMap, statusCode, responseBody);
                return null;
            }

            // 返回 JSON 格式的响应体
            return responseBody;
        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("authLogin Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("authLogin HTTP request failed. Status code: {}",e.getMessage(), e);
            }
//            JwtTokenCache.put(username, null);
            return null;
        }
    }

    /**
     * 更新设备的属性数据
     *
     * @param deviceId
     * @param scope
     * @param data
     * @return
     */
    public boolean updateDeviceAttributes(String deviceId, String scope, String data, String token) {
        //校验数据是否合规
        if (!JsonUtils.isJson(data) || StringUtils.isBlank(deviceId) || StringUtils.isBlank(scope)) {
            return false;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(data, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.UPDATE_DEVICE_ATTRIBUTES.replace("{deviceId}", deviceId).replace("{scope}", scope);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## updateDeviceAttributes 执行结束： url:{},data：{},  statusCode={}, 结果={}", url, data, statusCode, responseEntity);
                return false;
            }else {
                log.warn("## updateDeviceAttributes url:{}, 执行结束： statusCode={}", url, statusCode);
                return true;
            }
        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("updateDeviceAttributes Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("updateDeviceAttributes HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }


    /**
     * 更新设备的遥测数据
     *
     * @param deviceId
     * @param data
     * @return
     */
    public boolean updateDeviceTelemetry(String deviceId, String data,String token) {
        //校验数据是否合规
        if (!JsonUtils.isJson(data) || StringUtils.isBlank(deviceId)) {
            return false;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(data, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.UPDATE_DEVICE_TELEMETRY.replace("{entityId}", deviceId).replace("{entityType}", "DEVICE");
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();

            log.warn("## updateDeviceTelemetry url:{}, 执行结束： statusCode={}, 结果={}", url, statusCode, responseBody);

        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("updateDeviceTelemetry Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("updateDeviceTelemetry HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

        return true;

    }

    /**
     * 获取设备信息
     *
     * @param deviceId
     * @param token
     * @return
     */
    public DeviceBasicData getDeviceInfo(String deviceId, String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_INFO.replace("{deviceId}", deviceId);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String,Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceInfo 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return null;
            }
            DeviceBasicData data = new DeviceBasicData();
            Map<String, Object> responseBody = responseEntity.getBody();
            Object id = ((Map)responseBody.get("id")).get("id");
//            Object profiledId = ((Map)responseBody.get("deviceProfileId")).get("id");
            Object name = responseBody.get("name");
//            Object type = responseBody.get("type");
            data.setCoreId((String) id);
//            data.setProfileId((String) profiledId);
            data.setName((String) name);

            return data;

        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceInfo Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceInfo 404 failed");
                return null;
            }else {
                // 处理其他 HTTP 异常
                log.error("getDeviceInfo HTTP request failed. Status code: {}, url:{}", e.getStatusCode(), url);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 获取设备配置信息
     *
     * @param deviceProfileId
     * @param token
     * @return
     */
    public DeviceProfileData getDeviceProfileInfo(String deviceProfileId, String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceProfileId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_PROFILE_INFO.replace("{deviceProfileId}", deviceProfileId);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String,Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceProfileInfo 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return null;
            }
            DeviceProfileData data = new DeviceProfileData();
            Map<String, Object> responseBody = responseEntity.getBody();
            Object id = ((Map)responseBody.get("id")).get("id");
            Object name = responseBody.get("name");
            data.setProfileId((String) id);
            data.setName((String) name);
            return data;

        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceProfileInfo Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else if (HttpStatus.FORBIDDEN.equals(e.getStatusCode())
                    || HttpStatus.NOT_FOUND.equals(e.getStatusCode())
                    || HttpStatus.BAD_REQUEST.equals(e.getStatusCode())
            ) {
                // 处理身份验证失败的情况
                log.error("getDeviceProfileInfo not found. url:{}, statusCode={}", url, e.getStatusCode());
                return null;
            } else{
                // 处理其他 HTTP 异常
                log.error("getDeviceProfileInfo HTTP request failed. Status code: {}, url:{}", e.getStatusCode(), url);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 获取设备属性数据
     *
     * @param deviceId
     * @param token
     * @return
     */
    public List<DeviceAttributesData> getDeviceAttributes(String deviceId, String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_ATTRIBUTES.replace("{deviceId}", deviceId);
        try {
            // 期望 JSON 响应
            ResponseEntity<List<DeviceAttributesData>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<List<DeviceAttributesData>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            List<DeviceAttributesData> responseBody = responseEntity.getBody();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceAttributes 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseBody);
                return null;
            }

            return responseBody;

        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceAttributes Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceAttributes HTTP request failed. Status code: {}, url:{}", e.getStatusCode(), url);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 获取设备历史遥测数据
     *
     * @param deviceId
     * @param token
     * @return
     */
    public Map<String, List<DeviceTimeSeries>> getDeviceTimeSeries(String deviceId, String token, String[] keys, long startTime, long endTime, int limit, boolean desc,Long interval,String agg,Boolean useStrictDataTypes) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)||keys.length==0) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        Map<String, List<DeviceTimeSeries>> result = new HashMap<>();
        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_TIME_SERIES.replace("{deviceId}", deviceId);
        // 构建请求参数
        String orderBy = desc ? "DESC" : "ASC";

        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
                .queryParam("startTs", startTime)
                .queryParam("endTs", endTime)
                .queryParam("orderBy", orderBy);
        if (limit > 0){
            builder.queryParam("limit", limit);
        }
        if (keys.length > 0){
            String keysStr = String.join(",", keys);
            builder.queryParam("keys", keysStr);
        }
        if (interval != null){
            builder.queryParam("interval", interval);
        }
        if (agg != null){
            builder.queryParam("agg", agg);
        }
        if (useStrictDataTypes != null){
            builder.queryParam("useStrictDataTypes", useStrictDataTypes);
        }
        url = builder.toUriString();

        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, List<Object>>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String, List<Object>>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceTimeSeries 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return null;
            }
            Map<String, List<Object>> responseBody = responseEntity.getBody();
            for (String key : responseBody.keySet()){
                List<DeviceTimeSeries> deviceTimeSeriesList = new ArrayList<>();
                for (Object obj : (List)responseBody.get(key)){
                    Map<String, Object> map = (Map)obj;
                    DeviceTimeSeries deviceTimeSeries = new DeviceTimeSeries(map.get("ts").toString(), map.get("value").toString());
                    deviceTimeSeriesList.add(deviceTimeSeries);
                }
                result.put(key, deviceTimeSeriesList);
            }

            return  result;
        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceTimeSeries Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceTimeSeries HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }


    /**
     * 动态创建设备
     *
     * @param data
     * @param token
     * @return
     */
    public CreateGwRsp dynamicCreateDevice(String data, String token) {
        //校验数据是否合规
        if (!JsonUtils.isJson(data) || StringUtils.isBlank(token)) {
            return null;
        }
        CreateGwRsp result = new CreateGwRsp();
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(data, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.DYNAMIC_CREATE_DEVICE;
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );
            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## dynamicCreateDevice 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return null;
            }

            Map<String, Object> responseBody = responseEntity.getBody();

            log.warn("## dynamicCreateDevice 执行结束： statusCode={}, 结果={}", statusCode, responseBody);
            Map idMap = (Map)responseBody.get("id");
            result.setId(idMap.get("id").toString());
            Map tenantMap = (Map)responseBody.get("tenantId");
            result.setTenantId(tenantMap.get("id").toString());
            result.setCreatedTime(responseBody.get("createdTime").toString());
            return result;
        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("dynamicCreateDevice failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("dynamicCreateDevice HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }


    /**
     * 获取设备最新的遥测数据
     *
     * @param deviceId
     * @param token
     * @return
     */
    public Map<String, List<DeviceTimeSeries>> getDeviceTimeSeriesLatest(String deviceId, String token, String[] keys,Boolean useStrictDataTypes) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        Map<String, List<DeviceTimeSeries>> result = new HashMap<>();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_TIME_SERIES_LATEST.replace("{deviceId}", deviceId);
        // 构建请求参数


        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        if (keys.length >0){
            String keysStr = String.join(",", keys);
            builder.queryParam("keys", keysStr);
        }

        if (useStrictDataTypes != null){
            builder.queryParam("useStrictDataTypes", useStrictDataTypes);
        }
        url = builder.toUriString();

        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceTimeSeriesLatest 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return null;
            }
            Map<String, Object> responseBody = responseEntity.getBody();
            for (String key : responseBody.keySet()){
                List<DeviceTimeSeries> deviceTimeSeriesList = new ArrayList<>();
                for (Object obj : (List)responseBody.get(key)){
                    Map<String, Object> map = (Map)obj;
                    DeviceTimeSeries deviceTimeSeries = new DeviceTimeSeries(map.get("ts").toString(), map.get("value").toString());
                    deviceTimeSeriesList.add(deviceTimeSeries);
                }
                result.put(key, deviceTimeSeriesList);
            }

            return  result;

        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceTimeSeriesLatest Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceTimeSeriesLatest HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }


    /**
     * 删除设备
     *
     * @param deviceId
     * @return
     */
    public boolean deleteDevice(String deviceId,String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(deviceId)) {
            return false;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.DELETE_DEVICE.replace("{deviceId}", deviceId);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.DELETE,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();

            log.warn("## deleteDevice Url:{}, 执行结束： statusCode={}, 结果={}", url, statusCode, responseBody);

        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("deleteDevice Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("deleteDevice HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
        return true;

    }

    /**
     * 获取设备某个属性数据
     *
     * @param deviceId
     * @param token
     * @param keys
     * @return
     */
    public Map<String,Object> getDeviceAttributes(String deviceId, String token,String[] keys) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_ATTRIBUTES.replace("{deviceId}", deviceId);
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        if (keys.length >0){
            String keysStr = String.join(",", keys);
            builder.queryParam("keys", keysStr);
        }
        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity<List<DeviceAttributesData>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<List<DeviceAttributesData>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            List<DeviceAttributesData> responseBody = responseEntity.getBody();
            LinkedHashMap<String, Object> result = new LinkedHashMap<>();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceAttributes 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseBody);
                return null;
            }
            if(responseBody.size() > 0){
                for (DeviceAttributesData item: responseBody){
                    result.put(item.getKey(),item.getValue());
                }
                return result;
            }

            return null;

        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceAttributes Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else if(HttpStatus.NOT_FOUND.equals(e.getStatusCode())){
                log.error("getDeviceAttributes device not found, url:{}", url);
                throw new TokenException(ErrorCodeEnum.ILLEGAL_DEVICE_NOT_EXIST);
            }else {
                // 处理其他 HTTP 异常
                log.error("getDeviceAttributes HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }
    /**
     * 获取租户下设备列表
     *
     * @param token
     * @param deviceId
     * @return
     */
    public List<DeviceBasicData> getFromRelationsInfo(String token, String deviceId) {
        List<DeviceBasicData> result = new ArrayList();
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            log.error("## getFromRelationsInfo 参数不合规, token:{}, gwId:{}", token, deviceId);
            return result;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_RELATIONS_INFO;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("toId", deviceId);
        builder.queryParam("toType", "DEVICE");

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getFromRelationsInfo 执行结束： url:{}, statusCode={}, 结果={}", url, responseEntity);
                return result;
            }
            List<Map<String, Object>> responseBody = (List<Map<String, Object>>) responseEntity.getBody();
            for (int i = 0; i < responseBody.size(); i++) {
                DeviceBasicData deviceBasicData = new DeviceBasicData();
                Map jsonObject = responseBody.get(i);
                if(!"Created".equals(jsonObject.get("type").toString())){
                    continue;
                }
                Map toMap = (Map) jsonObject.get("from");
                String gwId = (String) toMap.get("id");
                String name = (String) jsonObject.get("fromName");
                deviceBasicData.setCoreId(gwId);
                deviceBasicData.setName(name);
                result.add(deviceBasicData);
            }
            return result;
        } catch (Exception e) {
            log.error("getFromRelationsInfo error:{}",e);
            throw e;
        }
    }

    /**
     * 获取设备id数据
     * 通过设备名称获取
     *
     * @param deviceName
     * @param token
     * @return
     */
    public DeviceBasicData getDeviceByDeviceName(String deviceName, String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceName)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        DeviceBasicData data = new DeviceBasicData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_TENANT_DEVICES;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        if(StringUtils.isNotBlank(deviceName)){
            builder.queryParam("deviceName", deviceName);
        }

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceByDeviceName 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseBody);
                return null;
            }
            Object id = ((Map)responseBody.get("id")).get("id");
            Object profiledId = ((Map)responseBody.get("deviceProfileId")).get("id");
            Object name = responseBody.get("name");
//            Object type = responseBody.get("type");
            data.setCoreId((String) id);
            data.setDeviceProfileId((String) profiledId);
            data.setName((String) name);
            Object tenantId = ((Map)responseBody.get("tenantId")).get("id");
            data.setTenantId((String) tenantId);
            log.debug("data: {}",data);
            return data;

        } catch (HttpClientErrorException e) {
            if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceByDeviceName 404 failed. Invalid username or password.");
                return null;
            }
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceByDeviceName Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceByDeviceName HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }


    /**
     * 获取设备
     * 通过设备名称获取
     *
     * @param deviceId
     * @param token
     * @return
     */
    public DeviceCredentialsData getDeviceCredentials(String deviceId, String token) {
        HttpHeaders headers = new HttpHeaders();
        DeviceCredentialsData data = new DeviceCredentialsData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_CREDENTIALS.replace("{deviceId}", deviceId);;
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceCredentials 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseBody);
                return null;
            }
            Object id = ((Map)responseBody.get("deviceId")).get("id");
            Object credentialsType = responseBody.get("credentialsType");
            Object credentialsValue = responseBody.get("credentialsValue");
            data.setCoreId((String) id);
            data.setCredentialsValue((String) credentialsType);
            data.setCredentialsValue((String) credentialsValue);
            log.debug("getDeviceCredentials data: {}",data);
            return data;

        } catch (HttpClientErrorException e) {
            if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceCredentials 404 failed. Invalid username or password.");
                return null;
            }
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceCredentials Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceCredentials HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 获取设备id数据
     * 通过设备名称获取
     *
     * @param token
     * @return
     */
    public Map deviceList(String token) {
        //校验数据是否合规
        if (StringUtils.isBlank(token)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_TENANT_DEVICE_INFOS;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("pageSize", 100);
        builder.queryParam("page", 0);
        builder.queryParam("active", true);

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, Object> responseBody = responseEntity.getBody();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceByDeviceName 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseBody);
                return null;
            }
            return responseBody;

        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("deviceList Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("deviceList HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 通过名称获取设备配置
     *
     * @param token
     * @return
     */
    public List<DeviceProfileData> getDeviceProfileInfos(String token) {
        List<DeviceProfileData> result = new ArrayList<>();
        //校验数据是否合规
        if (StringUtils.isBlank(token)) {
            log.error("## getDeviceProfileInfos 参数不合规, token:{}", token);
            return result;
        }
        HttpHeaders headers = new HttpHeaders();
        DeviceBasicData data = new DeviceBasicData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_DEVICE_PROFIELEINFOS;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("pageSize", 100);
        builder.queryParam("page", 0);
        builder.queryParam("page", 0);
        builder.queryParam("sortProperty", "name");

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getDeviceProfileInfos 执行结束： url:{}, statusCode={}, 结果={}", url, statusCode, responseEntity);
                return result;
            }
            Map<String, Object> responseBody = responseEntity.getBody();
            List dataArray = (List) responseBody.get("data");
            for (int i = 0; i < dataArray.size(); i++) {
                DeviceProfileData deviceProfileData = new DeviceProfileData();
                Map jsonObject = (Map) dataArray.get(i);
                Map idMap = (Map) jsonObject.get("id");
                deviceProfileData.setProfileId((String) idMap.get("id"));
                deviceProfileData.setName((String) jsonObject.get("name"));
                result.add(deviceProfileData);
            }
            return result;
        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getDeviceProfileInfos Authentication failed. Invalid username or password.", e);
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getDeviceProfileInfos HTTP request failed. Status code: {}", e.getStatusCode(), e);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }

    }

    /**
     * 获取租户下设备列表
     *
     * @param token
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult getTenantDevices(String token, Integer page, Integer pageSize) {
        PageResult result = new PageResult();
        //校验数据是否合规
        if (StringUtils.isBlank(token)) {
            log.error("## getTenantDevices 参数不合规, token:{}", token);
            return result;
        }
        HttpHeaders headers = new HttpHeaders();
        DeviceBasicData data = new DeviceBasicData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_TENANT_DEVICES;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("pageSize", pageSize);
        builder.queryParam("page", page);
        builder.queryParam("sortProperty", "name");

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String,Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getTenantDevices 执行结束： url:{}, statusCode={}, 结果={}", url, responseEntity);
                return result;
            }
            Map<String, Object> responseBody = responseEntity.getBody();
            List dataArray = (List) responseBody.get("data");
            List<String> gatewayProfileIds = getGwTypeList(token).stream().map(DeviceProfileData::getProfileId).collect(Collectors.toList());
            List<DeviceBasicData> dataList = new ArrayList<>();
            for (int i = 0; i < dataArray.size(); i++) {
                DeviceBasicData deviceBasicData = new DeviceBasicData();
                Map jsonObject = (Map) dataArray.get(i);
                Map idMap = (Map) jsonObject.get("id");
                deviceBasicData.setCoreId((String) idMap.get("id"));
                deviceBasicData.setName((String) jsonObject.get("name"));
                deviceBasicData.setCreatedTime(DateUtil.formatDateTime(new Date(Long.parseLong(jsonObject.get("createdTime").toString()))));
                Map deviceProfileIdMap = (Map) jsonObject.get("deviceProfileId");
                if(deviceProfileIdMap != null){
                    deviceBasicData.setDeviceProfileId((String) deviceProfileIdMap.get("id"));
                }
                if(gatewayProfileIds.contains(deviceBasicData.getDeviceProfileId())){
                    deviceBasicData.setType(DeviceTypeEnum.GW.getCode());
                }else{
                    deviceBasicData.setType(DeviceTypeEnum.DEVICE.getCode());
                }
                Map<String, Object> deviceAttributes = getDeviceAttributes(deviceBasicData.getCoreId(), token, new String[]{"lastConnectTime,ModelId,ModelId_1"});
                if(deviceAttributes.isEmpty()){
                    log.error("deviceAttributes deviceId:{} getDeviceAttributes type not found", deviceBasicData.getCoreId());
                    continue;
                }

                String modelId = null;
                if(deviceAttributes.get("ModelId")!=null){
                    modelId = deviceAttributes.get("ModelId").toString();
                }else if(deviceAttributes.get("ModelId_1")!=null){
                    modelId = deviceAttributes.get("ModelId_1").toString();
                }else{
                    modelId = "UNDEFINED";
                }
                if(deviceAttributes.get("ModelId")!=null){
                    modelId = deviceAttributes.get("ModelId").toString();
                }
                if(deviceAttributes.get("ModelId_1")!=null){
                    modelId = deviceAttributes.get("ModelId_1").toString();
                }
                long lastActivityTime = deviceAttributes.get("lastActivityTime")==null? 0L : Long.parseLong(deviceAttributes.get("lastActivityTime").toString());
                long now = System.currentTimeMillis();
                if (deviceAttributes.get("devStatus")==null){
                    long online = ONLINE_MILLISECOND;
                    if(modelOnlineMap.get(modelId)!=null){
                        online = modelOnlineMap.get(modelId);
                    }
                    if(now - lastActivityTime > online * 3L){
                        deviceBasicData.setStatus(0);
                    }else {
                        deviceBasicData.setStatus(1);
                    }
                }else {
                    deviceBasicData.setStatus(Integer.parseInt(deviceAttributes.get("devStatus").toString()));
                }
                deviceBasicData.setModelId(modelId);
                dataList.add(deviceBasicData);
            }
            result.setDataList(dataList);
            result.setPageNo(page);
            result.setPageSize(pageSize);
            result.setTotal((Integer) responseBody.get("totalElements"));
            result.setTotalPages((Integer) responseBody.get("totalPages"));
            return result;
        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getTenantDevices Authentication failed. Invalid username or password.", e);
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getTenantDevices HTTP request failed. Status code: {}", e.getStatusCode(), e);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }

    /**
     * 获取租户下设备列表
     *
     * @param token
     * @param gwId
     * @return
     */
    public List<DeviceBasicData> getRelationsInfo(String token, String gwId) {
        List result = new ArrayList();
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(gwId)) {
            log.error("## getRelationsInfo 参数不合规, token:{}, gwId:{}", token, gwId);
            return result;
        }
        HttpHeaders headers = new HttpHeaders();
        DeviceBasicData data = new DeviceBasicData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_RELATIONS_INFO;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("fromId", gwId);
        builder.queryParam("fromType", "DEVICE");

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getRelationsInfo 执行结束： url:{}, statusCode={}, 结果={}", url, responseEntity);
                return result;
            }
            List<Map<String, Object>> responseBody = (List<Map<String, Object>>) responseEntity.getBody();
            for (int i = 0; i < responseBody.size(); i++) {
                DeviceBasicData deviceBasicData = new DeviceBasicData();
                Map jsonObject = responseBody.get(i);
                Map toMap = (Map) jsonObject.get("to");
                String deviceId = (String) toMap.get("id");
                String name = (String) jsonObject.get("toName");
                deviceBasicData.setCoreId(deviceId);
                deviceBasicData.setName(name);
                deviceBasicData.setType(DeviceTypeEnum.DEVICE.getCode());
                result.add(deviceBasicData);
            }
            return result;
        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getRelationsInfo Authentication failed. Invalid username or password.", e);
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            }if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
                log.error("getRelationsInfo NOT_FOUND .", e);
                return result;
            } else {
                // 处理其他 HTTP 异常
                log.error("getRelationsInfo HTTP request failed. Status code: {}", e.getStatusCode(), e);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }

    /**
     * 获取租户下设备列表
     *
     * @param token
     * @return
     */
    public PageResult getAlarms(String token, AlarmsPageRequest alarmsPageRequest) {
        PageResult result = new PageResult();
        //校验数据是否合规
        if (StringUtils.isBlank(token)) {
            log.error("## getAlarms 参数不合规, token:{}, gwId:{}", token);
            return result;
        }
        HttpHeaders headers = new HttpHeaders();
        DeviceBasicData data = new DeviceBasicData();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_ALARMS;
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("pageSize", alarmsPageRequest.getPageSize());
        builder.queryParam("page", alarmsPageRequest.getPageNo());
        builder.queryParam("startTime", DateUtil.parse(alarmsPageRequest.getStartTime(), "yyyy-MM-dd HH:mm:ss").getTime());
        builder.queryParam("endTime", DateUtil.parse(alarmsPageRequest.getEndTime(), "yyyy-MM-dd HH:mm:ss").getTime());
        builder.queryParam("sortProperty", "createdTime");
        builder.queryParam("sortOrder", "DESC");

        url = builder.toUriString();
        try {
            // 期望 JSON 响应
            ResponseEntity responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getAlarms 执行结束： url:{}, statusCode={}, 结果={}", url, responseEntity);
                return result;
            }
            Map<String, Object> responseBody = (Map<String, Object>) responseEntity.getBody();
            List dataArray = (List) responseBody.get("data");
            List<AlarmData> dataList = new ArrayList<>();
            for (int i = 0; i < dataArray.size(); i++) {
                AlarmData alarmData = new AlarmData();
                Map jsonObject = (Map) dataArray.get(i);
                alarmData.setName((String)jsonObject.get("name"));
                alarmData.setStatus((String)jsonObject.get("status"));
                alarmData.setType((String)jsonObject.get("type"));
                alarmData.setStartTs(jsonObject.get("startTs")==null? "":
                        DateUtil.format(new Date(Long.parseLong(jsonObject.get("startTs").toString())), "yyyy-MM-dd hh:mm:ss"));
                alarmData.setAckTs(jsonObject.get("ackTs")==null|| "0".equals(jsonObject.get("ackTs").toString())? "":
                        DateUtil.format(new Date(Long.parseLong(jsonObject.get("ackTs").toString())), "yyyy-MM-dd hh:mm:ss"));
                alarmData.setClearTs(jsonObject.get("clearTs")==null|| "0".equals(jsonObject.get("clearTs").toString())? "":
                        DateUtil.format(new Date(Long.parseLong(jsonObject.get("clearTs").toString())), "yyyy-MM-dd hh:mm:ss"));
                alarmData.setEndTs(jsonObject.get("endTs")==null|| "0".equals(jsonObject.get("endTs").toString())? "":
                        DateUtil.format(new Date(Long.parseLong(jsonObject.get("endTs").toString())), "yyyy-MM-dd hh:mm:ss"));
                alarmData.setCreatedTime(jsonObject.get("createdTime")==null? "":
                        DateUtil.format(new Date(Long.parseLong(jsonObject.get("createdTime").toString())), "yyyy-MM-dd hh:mm:ss"));

                Map originatorMap = (Map) jsonObject.get("originator");
                alarmData.setDeviceId((String)originatorMap.get("id"));
                alarmData.setDeviceName((String)jsonObject.get("originatorName"));
                alarmData.setDeviceLabel((String)jsonObject.get("originatorLabel"));

                Map idMap = (Map) jsonObject.get("id");
                alarmData.setId((String)idMap.get("id"));

                Map tenantIdMap = (Map) jsonObject.get("tenantId");
                alarmData.setTenantId((String)tenantIdMap.get("id"));
                dataList.add(alarmData);
            }
            result.setDataList(dataList);
            result.setPageNo(alarmsPageRequest.getPageNo());
            result.setPageSize(alarmsPageRequest.getPageSize());
            result.setTotal((Integer) responseBody.get("totalElements"));
            result.setTotalPages((Integer) responseBody.get("totalPages"));
            return result;
        } catch (HttpClientErrorException e) {
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("getAlarms Authentication failed. Invalid username or password.", e);
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("getAlarms HTTP request failed. Status code: {}", e.getStatusCode(), e);
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }

    /**
     * 删除遥测数据
     *
     * @param deviceId
     * @param token
     * @return
     */
    public Map<String, List<DeviceTimeSeries>> deleteDataTelemetry(String deviceId, String token, String[] keys) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.DELETE_DEVICE_TELEMETRY.replace("{deviceId}", deviceId);
        // 构建请求参数

        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        if (keys.length >0){
            String keysStr = String.join(",", keys);
            builder.queryParam("keys", keysStr);
            builder.queryParam("deleteAllDataForKeys", true);
        }


        url = builder.toUriString();

        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, List<DeviceTimeSeries>>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.DELETE,
                    entity,
                    new ParameterizedTypeReference<Map<String, List<DeviceTimeSeries>>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, List<DeviceTimeSeries>> responseBody = responseEntity.getBody();

            log.warn("## deleteDataTelemetry url:{}, 执行结束： statusCode={}, 结果={}",url, statusCode, responseBody);
            return  responseBody;

        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("deleteDataTelemetry Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("deleteDataTelemetry HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }

    /**
     * 删除属性数据
     *
     * @param deviceId
     * @param token
     * @return
     */
    public Map<String, List<DeviceTimeSeries>> deleteDataAttribute(String deviceId, String token, String[] keys) {
        //校验数据是否合规
        if (StringUtils.isBlank(token) || StringUtils.isBlank(deviceId)) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.DELETE_DEVICE_ATTRIBUTES.replace("{deviceId}", deviceId);
        // 构建请求参数

        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        if (keys.length >0){
            String keysStr = String.join(",", keys);
            builder.queryParam("keys", keysStr);
        }


        url = builder.toUriString();

        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, List<DeviceTimeSeries>>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.DELETE,
                    entity,
                    new ParameterizedTypeReference<Map<String, List<DeviceTimeSeries>>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            Map<String, List<DeviceTimeSeries>> responseBody = responseEntity.getBody();

            log.info("## deleteDataAttribute url:{}, 执行结束： statusCode={}, 结果={}", url, statusCode, responseBody);
            return  responseBody;

        } catch (HttpClientErrorException e) {
            log.error(e.getMessage(), e);
            // 捕获 HTTP 401 异常
            if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
                // 处理身份验证失败的情况
                log.error("deleteDataAttribute Authentication failed. Invalid username or password.");
                throw new TokenException(ErrorCodeEnum.USER_LOGIN_TOKEN_EXPIRE);
            } else {
                // 处理其他 HTTP 异常
                log.error("deleteDataAttribute HTTP request failed. Status code: {}", e.getStatusCode());
                throw new BaseException(ErrorCodeEnum.SYSTEM_ERROR);
            }
        }
    }
    public String getToken() {
        //根据邮箱查询用户名和密码
        String token = null;
        String mail = "marketing@rexolar.com";
        String mailPassword = "Rex_sysadmin!@";
        try {
            Map map = authLogin(mail, mailPassword);
            if(map ==null){
                log.error("RexolarApiClient 获取token失败, mail1:{}, mailPassword:{}", mail, mailPassword);
            }
            token = map.getOrDefault("token", "").toString();
            userTokenCache.put(mail, token);
        }catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return token;
    }

    public String getTenantToken(String tenantId) {
        String token = userTokenCache.getIfPresent(tenantId);
        if(StringUtils.isNotBlank(token)){
            return token;
        }
        //根据邮箱查询用户名和密码
        String sysToken = getToken();
        List<UserBasicData> users = getTenantUsers(tenantId, sysToken);
        if(CollectionUtils.isEmpty(users)){
            log.error("RexolarApiClient getTenantToken 租户下用户列表为空, tenantId:{}", tenantId);
            return null;
        }
        Map userToken =  getUserToken(users.get(0).getId(), sysToken);
        if(userToken ==null){
            log.error("RexolarApiClient getTenantToken 获取租户token失败, tenantId:{}", tenantId);
            return null;
        }
        token = userToken.getOrDefault("token", "").toString();
        userTokenCache.put(tenantId, token);
        return token;
    }

    public Map getUserToken(String userId, String token) {
        HttpHeaders headers = new HttpHeaders();

        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_USER_TOKEN.replace("{userId}", userId);
        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getUserToken 执行结束： url:{}, statusCode={}", url, statusCode);
                return null;
            }
            Map<String, Object> responseBody = responseEntity.getBody();
            return responseBody;

        } catch (Exception e) {
            log.error("getUserToken error:{}",e.getMessage());
            throw e;
        }
    }

    /**
     * 获取租户下用户信息
     *
     * @param tenantId
     * @param token
     * @return
     */
    public List<UserBasicData> getTenantUsers(String tenantId, String token) {
        HttpHeaders headers = new HttpHeaders();
        List<UserBasicData> dataList = new ArrayList<>();
        headers.add("Content-Type", "application/json");
        headers.add("accept", "application/json");
        headers.add("X-Authorization", "Bearer " + token);

        HttpEntity<String> entity = new HttpEntity<>(null, headers);

        //构建请求链接
        String url = customConfig.getHttpApi() + ApiConstant.GET_TENANT_USERS.replace("{tenantId}", tenantId);
        // 构建请求参数
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
                .queryParam("page", 0)
                .queryParam("pageSize", 1000)
                .queryParam("sortProperty", "createdTime")
                .queryParam("sortOrder", "DESC");
        url = builder.toUriString();

        try {
            // 期望 JSON 响应
            ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    }
            );

            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("## getTenantUsers 执行结束： url:{}, statusCode={}", url, statusCode);
                return null;
            }Map<String, Object> responseBody = responseEntity.getBody();
            List<Map> data = (List<Map>) responseBody.get("data");
            for(Map item: data){
                UserBasicData userBasicData = new UserBasicData();
                Object id = ((Map)item.get("id")).get("id");
                Object phone = item.get("phone");
                Object name = item.get("name");
                Object type = item.get("email");
                Object authority = item.get("authority");
                userBasicData.setId((String) id);
                userBasicData.setTenantId(tenantId);
                userBasicData.setName((String) name);
                userBasicData.setEmail((String) type);
                userBasicData.setAuthority((String) authority);
                userBasicData.setPhone((String) phone);
                dataList.add(userBasicData);
            }
            return  dataList;
        } catch (HttpClientErrorException ex){
            log.error("## getTenantUsers 执行结束： url:{}, statusCode={}, 结果={}", url, ex.getStatusCode(), ex.getResponseBodyAsString());
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND){
                return dataList;
            }
        } catch (Exception e) {
            log.error("getTenantUsers error:{}",e.getMessage());
            throw e;
        }
        return dataList;
    }

    public List<DeviceProfileData> getGwTypeList(String token) {
        List<DeviceProfileData> gwTypeList = new ArrayList<>();
        List<DeviceProfileData> list = getDeviceProfileInfos(token);
        for (DeviceProfileData deviceProfileData:list){
            if(deviceProfileData.getName().contains("gateway")){
                gwTypeList.add(deviceProfileData);
            }
        }
        return gwTypeList;
    }
}
